using System;
using System.IO;

namespace OR.Lazarus.Utility
{
	/// <summary>
	/// Summary description for FileMerger.
	/// </summary>
	public class FileRegionMerger
	{
		public const string	REGION_START	= "#lazgen";
		public const string	REGION_END		= "#endlazgen";

		public virtual string GetText( Stream pSource )
		{
			string		vReturn	= String.Empty;
			pSource.Seek( 0, SeekOrigin.Begin );

			TextReader	vReader	= new StreamReader( pSource );

			vReturn = vReader.ReadToEnd();

			return ( vReturn );
		}

		public virtual Stream Merge( Stream pSource, Stream pTarget )
		{
			Stream			vReturn			= new MemoryStream();
			string			vSourceText		= this.GetText( pSource );
			string			vTargetText		= this.GetText( pTarget );

			string[]	vSourceRegions	= this.GetRegions( vSourceText );
			string[] vTargetRegions	= this.GetRegions( vTargetText );

			string	vSourceRegion	= String.Empty;

			foreach ( string vRegionName in vSourceRegions )
			{
				vSourceRegion = this.GetRegion( vSourceText, vRegionName );

				vTargetText = this.MergeRegion( vSourceRegion, vTargetText, vRegionName );
			}

			StreamWriter	vWriter	= new StreamWriter( vReturn );

			vWriter.Write( vTargetText );

			vWriter.Flush();

			return ( vReturn );
		}

		public virtual string[] GetRegions( string pSource )
		{
			int		vStartPos		= 0;
			int		vReturnCount	= 0;
			string[]	vReturn			= new string[ this.GetRegionCount( pSource ) ];
			int		vIndex			= pSource.IndexOf( REGION_START, vStartPos, pSource.Length - vStartPos );

			while ( vIndex > -1 )
			{
				vStartPos = vIndex + REGION_START.Length + 1;

				vReturn[ vReturnCount ] = pSource.Substring( vStartPos, pSource.IndexOf( "#", vStartPos ) - vStartPos );
				
				vReturnCount++;

				vIndex		= pSource.IndexOf( REGION_START, vStartPos, pSource.Length - vStartPos );
			}

			return ( vReturn );
		}

		public virtual int GetRegionCount( string pSource )
		{
			int	vReturn		= 0;
			int	vStartPos	= 0;
			int	vIndex		= pSource.IndexOf( REGION_START, vStartPos, pSource.Length - vStartPos );

			while ( vIndex > -1 )
			{
				vReturn++;

				vStartPos = vIndex + REGION_START.Length;

				vIndex		= pSource.IndexOf( REGION_START, vStartPos, pSource.Length - vStartPos );
			}
			
			return ( vReturn );
		}

		public virtual string GetRegionTag( string pRegionName, string pRegionType )
		{
			string	vReturn = String.Format( "{0} {1}#", pRegionType, pRegionName );

			return ( vReturn );
		}

		public virtual string MergeRegion( string pSourceRegion, string pTarget, string pRegionName )
		{
			string	vStartTag	= this.GetRegionTag( pRegionName, REGION_START );
			string	vEndTag		= this.GetRegionTag( pRegionName, REGION_END );

			int		vStartPos	= pTarget.IndexOf( vStartTag ) + vStartTag.Length;
			int		vEndPos		= pTarget.IndexOf( vEndTag );

			string	vReturn		= String.Empty;

			if ( vEndPos > 0 )
			{
				vReturn					=	pTarget.Substring( 0, vStartPos );
				vReturn					+= pSourceRegion;
				vReturn					+= pTarget.Substring( vEndPos, pTarget.Length - vEndPos );
			}

			return ( vReturn );
		}

		public virtual string GetRegion( string pSource, string pName )
		{
			string	vReturn		= String.Empty;
			string	vStartTag	= this.GetRegionTag( pName, REGION_START );
			string	vEndTag		= this.GetRegionTag( pName, REGION_END );
			int		vStartPos	= pSource.IndexOf( vStartTag ) + vStartTag.Length;
			int		vEndPos		= pSource.IndexOf( vEndTag );

			vReturn = pSource.Substring( vStartPos, vEndPos - vStartPos );

			return ( vReturn );
		}

		public FileRegionMerger()
		{
			//
			// TODO: Add constructor logic here
			//
		}
	}
}
